﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Collections;
using System.IO;
using System.Dynamic;
using System.Diagnostics.Contracts;

namespace ConsoleApplication1
{
    public class Employee : DynamicObject
    {

        Dictionary<string, object> properties = new Dictionary<string, object>();

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (properties.ContainsKey(binder.Name))
            {
                result = properties[binder.Name];
                return true;
            }
            else
            {
                result = "Invalid Property!";
                return false;
            }
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            properties[binder.Name] = value;
            return true;
        }

        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            dynamic method = properties[binder.Name];
            result = method(args[0].ToString(), args[1].ToString());
            return true;
        }
    }
    class Base
    {
        public virtual void Execute(object x)
        {
            //Console.WriteLine("object");
            Console.WriteLine("Base");

        }
    }
    class Derived : Base
    {
        public new void Execute(object x)
        {
            //Console.WriteLine("string");
            Console.WriteLine("Derived");

        }
    }
    class Foo
    {
        public static T DynamicSum<T>(IEnumerable<T> source)
        {
            T total = default(T);
            foreach (dynamic item in source)
            {
                if (item != null)
                {
                    total = (T)(total + item);
                }
            }
            return total;
        }

        //public static T? DynamicSum<T>( IEnumerable<T?> source)
        //   where T : struct
        //{
        //    T total = default(T);
        //    foreach (T? item in source)
        //    {
        //        if (item != null)
        //        {
        //            dynamic value = item.Value;
        //            total = (T)(total + value);
        //        }
        //    }
        //    return total;
        //}

        static void Execute(dynamic x, string y)
        {
            Console.WriteLine("dynamic, string");
        }
        static void Execute(dynamic x, object y)
        {
            Console.WriteLine("dynamic, object");
        }
        static void Main()
        {
            dynamic dyn = new StringBuilder();
            Console.WriteLine(Sqrt(9));
            //dynamic d = new Employee();
            //d.FirstName = "Tom";
            //d.LastName = "Jerry";
            //d.BirthDate = new DateTime(1960, 12, 01);

            //Func<string, string, string> method = (a, b) => a + " " + b;

            //d.GetData = method;
            //Console.WriteLine(d.FirstName + " " + d.LastName + "..." + d.GetData("Tom", "Jerry") + " - " + d.GetType());
            Base x = new Derived();
            x.Execute(1);

            Derived d = new Derived();
            ((Base)d).Execute(4);
            //IEnumerable<int> list = new int[] { 1, 2, 3 };
            ////DynamicSum(list);
            //DynamicSum(new int?[] { });
            //object text = "text";
            //dynamic d = 10;
            //Execute(d, (dynamic)text);
            //LARge array, use As Enumerable and compare perofrmance
            //Dog dgfgfg321 = new Dog();
            //CallFun(dgfgfg321);
            //StringBuilder sb = new StringBuilder("Zonka");
            //Console.WriteLine(sb.ToString());
            //Modify(sb);
            //Console.WriteLine(sb.ToString());
            //int[] arr = new int[] { 1, 2, 3 };
            ////PrintArr(arr, 3);
            //object o = DateTime.Now;
            //Console.WriteLine(o.GetType());
            //int xdfgdf987g = 5;
            //int? y = null;
            //int? z = null;
            //bool b = y == z;
            //if (xdfgdf987g==null)
            //{
            //    Console.WriteLine("dfdf");

            //}

            dynamic dgfgfg321 = 0;
            string xdfgdf987g = "text";
            var array = new[] { dgfgfg321, xdfgdf987g };
            //IList<Dog> dogs = new List<Dog>();

            //IEnumerable<Animal> animals = dogs;

            //Animal f;

            ////int x;
            //string str = "fhf";
            //Func<string, int, bool> fun = (g, f) => int.TryParse(g, out f);
            //Expression<Func<int, int, bool>> expression;
            ////expression = (x, y) => x > y;
            //int[] set = new int[] { 3, 34, 4, 12, 5, 2 };
            //int sum = 9;

            //Console.WriteLine("-------------{0}-------------",
            //expression);


        }

        private static string Sqrt(int n)
        {
            decimal low = 0;
            decimal high = n;
            while (high - low > 1)
            {
                decimal middle = (low + high) / 2;
                if (middle * middle < n)
                {
                    low = middle;
                }
                else
                {
                    high = middle;
                }
            }

            return low.ToString();
        }

        private static void CallFun(Dog d)
        {
            Console.WriteLine("Dog");
        }

        private static void CallFun(Animal d)
        {
            Console.WriteLine("Animal");
        }

        private static void PrintArr(int[] arr, int n)
        {
            if (n < 1)
            {
                return;
            }

            PrintArr(arr, n - 1);
            Console.WriteLine(arr[n - 1]);
        }

        private static void Modify(StringBuilder sb)
        {
            //sb.Append("NO!");
            sb = null;
        }


        private static string LongestSubstring(string word)
        {
            var set = new HashSet<char>();
            string longestOverAll = "";
            string longestTillNow = "";

            foreach (char c in word)
            {
                if (!set.Contains(c))
                {
                    longestTillNow += c;
                    set.Add(c);
                }
                else
                {
                    longestTillNow = string.Empty;
                }

                if (longestTillNow.Length > longestOverAll.Length)
                {
                    longestOverAll = longestTillNow;
                }
            }

            return longestOverAll;
        }



        public int Number { get; set; }
    }

    interface Animal
    {
    }

    struct Dog : Animal
    {
    }

}
